iT邦幫忙

0

# Day 29-30 Docker 通訊、模型負載與 LINE 限制完全解密、30 天完賽總結、開源專案全貌與 AI Agent 的下一站藍圖

n8n
  • 分享至 

  • xImage
  •  

在昨天的文章中,我們使用 GitHub Actions 建構了專業級的 CI 自動化測試管線,確保每次程式碼交付都能通過嚴密的品質檢驗。

從 Day 01 到現在,我們一步一腳印地把一套空白架構,打造成涵蓋 LINE Bot、n8n 工作流、Dify 意圖大腦、FastAPI 推薦微服務、Google Places API、SQLite/Redis 記憶庫 的完整雲原生 AI 系統。

然而,在技術文章中光鮮亮麗的成果背後,真實的工程實踐往往充滿了各種「看似莫名其妙、Debug 到深夜」的深坑。
今天 Day 29,我們不寫新功能,而是要進行一場深度技術覆盤(Post-Mortem):系統性盤點這趟旅程中踩過最具代表性的 5 大架構痛點、根本原因以及最佳避坑指南,為你的 AI Agent 工程化之路提供最接地氣的經驗沉澱!


一、系統全域架構拓撲回顧

在深入覆盤之前,我們先把整套系統的終極架構藍圖攤開:

               ┌───────────────────────┐
               │    LINE 官方客戶端     │
               └───────────┬───────────┘
                           │ 1. Webhook (HMAC-SHA256 簽章)
                           ▼
               ┌───────────────────────┐
               │   n8n 自動化工作流     │ ◄── [Day 20] Cron 排程推播
               └─────┬───────────┬─────┘
                     │           │
     (口語意圖分析)   │           │ (已具座標 / 抽籤 / Postback 直接調用)
                     ▼           │
     ┌──────────────────┐        │
     │  Dify (Gemini)   │        │
     │  提示詞防護加固   │        │
     └─────────┬────────┘        │
               │ (結構化 JSON)    │
               └──────────┬──────┴────────────────┐
                          ▼                       ▼
               ┌──────────────────────────────────────┐
               │         FastAPI 後端推薦微服務        │
               │  - Slowapi 慢速限流 (429 防刷)        │
               │  - FSM 多輪對話槽位狀態管理            │
               │  - Loguru 結構化日誌 + Sentry 告警   │
               └─────┬────────────────────┬───────────┘
                     │                    │
        (快取查詢 / 寫入) │                    │ (歷史足跡 / 收藏)
                     ▼                    ▼
     ┌──────────────────────┐  ┌──────────────────────┐
     │  Redis 快取 (Upstash) │  │  SQLite 資料庫 (ORM) │
     └──────────────┬───────┘  └──────────────────────┘
                    │ (Cache Miss)
                    ▼
     ┌──────────────────────┐
     │ Google Places (New)  │ ──> Field Masking 精準索取
     └──────────────────────┘

二、30 天五大核心踩坑覆盤與避坑指南

踩坑 1:Docker 容器間的通訊黑洞(localhost 的幻覺)
痛點現象:
在本地開發初期,n8n 與 FastAPI 分別以容器或本地行程運行。當 n8n 的 HTTP Request 節點填寫 http://localhost:8000 時,總是報出 ECONNREFUSED(連線遭拒)的錯誤。

根本原因:
容器內的 localhost 指向的是容器自己,而不是宿主機(Host Machine)!

終極解法:
1.若 n8n 跑在 Docker 容器內、FastAPI 跑在 Windows/Mac 本機:連線網址必須改用 http://host.docker.internal:8000。

2.若兩者都在 Docker 內:必須將兩者掛載到同一個 Docker Network(自訂橋接網路),直接以容器名稱(Container Name)相互呼叫(例如 http://fastapi-backend:8000)。
踩坑 2:大語言模型偶發 503 負載過載與格式崩潰
痛點現象:
Dify 在呼叫 Gemini 或其他 LLM 時,尖峰時段可能遇到 Google 回傳 503 Service Unavailable;或偶爾模型會在 JSON 外面包上一層 json,導致 n8n 的 JSON Parse 節點直接報錯中斷。

根本原因:
雲端模型具備不可控的網路波動與隨機推論特性,若工作流缺乏「重試(Retry)」與「容錯(Defensive Parsing)」機制,脆弱度會極高。

終極解法:
1.n8n 重試機制:在 HTTP Request 節點開啟 Retry on Fail,設定重試 2 次、間隔 2 秒,能平滑化 95% 以上的暫態 503 錯誤。

2.正規防禦解析:在 n8n Code 節點中,不要直接 JSON.parse(),先透過正則表示式 text.match(/{[\s\S]*}/) 抽出純 JSON 核心內容後再解析。
踩坑 3:LINE Flex Message 欄位超載與非法字元炸裂
痛點現象:
後端明明搜尋成功回傳了資料,但 LINE 機器人卻一片死寂,完全不回覆訊息,且 LINE API 回傳了 400 Bad Request: Invalid message format。

根本原因:
LINE Flex Message 對資料結構有嚴格的限制:

文字欄位若為 null 或未定義,整個 Flex JSON 直接無效!

Google Places 回傳的店家簡介若含有特殊未轉義換行符或長度超過上限,卡片渲染引擎會拒絕接收。

終極解法:
在組裝 Flex Bubble 時,對所有外部輸入加上嚴格的保底預設值與長度裁切(Truncate):

const shopName = (shop.name || '精選餐廳').substring(0, 30);
const shopAddress = (shop.location || '地址請參考地圖').substring(0, 45);

踩坑 4:FastAPI 非同步端點中的資料庫阻塞(Blocking DB)
痛點現象:
當多個使用者同時發起請求時,原本宣稱高效能的 FastAPI 竟然出現排隊卡頓的現象。

根本原因:
在 async def 端點中,若呼叫了標準的同步 SQLAlchemy 查詢(如 db.query(...).all()),Python 的單線程 Event Loop 會被該同步 I/O 阻塞住,導致其他請求無法切換處理。

終極解法:
1.對於高併發情境,改用 SQLAlchemy 2.0 的 AsyncSession 搭配 aiosqlite。

2.若維持同步 ORM,端點應宣告為一般的 def recommend_food(...)(FastAPI 會自動丟到外部執行緒池 ThreadPool 執行,避免卡死主事件迴圈)。
踩坑 5:Places API 帳單隱藏炸彈(未受限的欄位索取)
痛點現象:
測試幾十次後,查看 Google Cloud Console 帳單預估,費用增加的速度遠超預期。

根本原因:
呼叫 Google Places API (New) 時,若未加上 X-Goog-FieldMask 標頭,系統預設會抓取最貴的「進階資訊(Atmosphere / Reviews)」,費用直接乘以數倍!

終極解法:
嚴格規範 X-Goog-FieldMask,只勾選系統需要的基礎欄位(Basic SKU),並搭配 Day 24 的 Redis 快取與 Day 27 的 GCP 預算警報,達成零成本運轉。

三、架構迭代的反思

回顧整個 30 天的開發歷程,這套系統之所以具備生產級實用性,關鍵在於堅持了三項核心原則:
1.職責分離(Separation of Concerns):

溝通互動交給 LINE

工作流程編排交給 n8n

意圖辨識交給 Dify

商業邏輯與記憶交給 FastAPI
每個模組都是獨立解耦的,未來即使想換掉 LINE 改接 Discord 或 Slack,也只需改動工作流前端,核心後端完全不用重寫!

2.防禦性程式設計(Defensive Programming):
從限流(Slowapi)、提示詞加固(Injection Defense)、簽章比對(HMAC)到測試(Pytest),資安與穩定性從一開始就深植在架構中,而非上線後才打補丁。

3.極致的成本意識:
透過記憶體快取與條件繞道(GPS / 抽籤跳過 LLM),讓這套系統即使部署在真實環境中,每個月也幾乎不需要花費任何額外伺服器與 API 開銷。

Day 30 30天完賽總結、開源專案全貌與 AI Agent 的下一站藍圖

歷時整整 30 天,每天不間斷的架構設計、實作撰寫、除錯踩坑與覆盤記錄,我們終於抵達了這趟旅程的終點線!

回顧 Day 01,我們從一個最常見的生活痛點出發——「今天吃什麼?」。
如果只把 LLM 當成聊天框,那它永遠只能吐出幻覺連篇或脫離現實的文字;而真正的工程價值,在於如何將 AI 的推理能力,與真實世界的 API、雲原生微服務、工作流編排器、資料庫記憶以及安全性防護網深度結合。

今天 Day 30,我們將完整回顧這 30 天的技術全景、整理標準的開源專案規格與目錄架構,並展望 AI Agent 在未來工程落地上的延伸可能!


一、30 天技術全景心智地圖回顧

這 30 天的旅程可以精準拆解為五大演進階段:

【階段一:地基與架構誕生】(Day 01 ~ Day 07)
  ├── 釐清 AI Agent 架構與工具鏈選型
  ├── FastAPI 核心微服務建置與 Pydantic 嚴格型別校驗
  └── Dify + Gemini 意圖抽取大腦與本地 Docker 環境成型

【階段二:雲端通訊與介面】(Day 08 ~ Day 15)
  ├── LINE Messaging API 串接與 ngrok 穿透測試
  ├── n8n 視覺化工作流自動化編排
  ├── 精緻美觀的 LINE Flex Message Carousel 輪播卡片
  ├── Google Maps Places API (New) 真實餐廳資料落地
  └── SQLite 記憶庫整合與全雲端 PaaS 部署 (Render / Zeabur)

【階段三:進階互動與功能拓展】(Day 16 ~ Day 20)
  ├── LINE GPS 座標位置分享與方圓 1 公里雷達式精準搜尋
  ├── 有限狀態機(FSM)槽位填補與智慧主動追問
  ├── 隨機盲盒抽籤轉盤與 LINE Quick Reply 快速回覆
  ├── SQLite 私房名單收藏夾與 Postback 背景靜默操作
  └── n8n Cron 排程觸發器與 LINE Push API 午餐靈感主動推播

【階段四:企業級資安與效能】(Day 21 ~ Day 25)
  ├── Slowapi 慢速限流防護 (429 Too Many Requests)
  ├── System Prompt 提示詞加固與 Prompt Injection 越獄防禦
  ├── LINE Webhook HMAC-SHA256 數位簽章驗證 (X-Line-Signature)
  ├── Redis 快取架構 (Cache-Aside Pattern) 壓低 70 倍延遲與節省成本
  └── Pytest + TestClient 建立自動化單元與整合測試防線

【階段五:維運監控與工程交付】(Day 26 ~ Day 30)
  ├── Loguru 結構化日誌輪轉 + Sentry 實時異常捕獲告警
  ├── Token 用量與 Google API 成本盤點(達成零成本運轉)
  ├── GitHub Actions CI/CD 自動化測試與 Lint 檢查管線
  ├── 五大架構深度踩坑剖析與避坑實務覆盤
  └── Day 30 專案總整理與開源發布!

二、開源專案全貌與目錄結構規範

這套系統採用了高內聚、低耦合的模組化目錄結構,確保未來無論是要抽換 LLM 供應商、更換資料庫或擴充前端通訊平台,都能以最小成本無痛抽換:

food-agent-production/
├── .github/
│   └── workflows/
│       └── ci.yml             # GitHub Actions 自動化 CI 測試流水線
├── app/
│   ├── core/
│   │   ├── cache.py           # Redis 非同步快取服務層
│   │   ├── line_auth.py       # HMAC-SHA256 數位簽章驗證依賴
│   │   ├── limiter.py         # Slowapi 速率限制配置
│   │   ├── logger.py          # Loguru 結構化日誌設定
│   │   └── security.py        # 提示詞注入與正則安全過濾器
│   ├── models/
│   │   └── memory.py          # SQLAlchemy 資料表模型(使用者、歷史、收藏夾)
│   ├── routers/
│   │   ├── favorite.py        # 私房餐廳收藏夾管理 API
│   │   ├── health.py          # 容器健康檢查與 Sentry 測試端點
│   │   ├── push.py            # 主動推播訂閱名單 API
│   │   └── recommendation.py  # 核心推薦、抽籤與 FSM 狀態端點
│   ├── schemas/
│   │   └── food.py            # Pydantic 資料模型與列舉規範
│   ├── services/
│   │   └── places.py          # Google Places API 串接與快取整合
│   ├── config.py              # 全域環境變數配置
│   ├── database.py            # 資料庫連線引擎與 Session 管理
│   └── main.py                # FastAPI 核心入口與中介軟體掛載
├── n8n/
│   ├── line_core_flow.json    # n8n 核心訊息分流工作流匯出檔
│   └── lunch_push_flow.json   # n8n 每日定時推播工作流匯出檔
├── tests/
│   ├── conftest.py            # In-Memory SQLite 測試沙盒與客戶端
│   ├── test_health.py         # 健康檢查端點測試
│   ├── test_recommend.py      # 核心商業邏輯 Mock 測試
│   └── test_schemas.py        # Schema 驗證與資安過濾單元測試
├── .dockerignore
├── .env.example               # 環境變數設定範本檔
├── .flake8                    # 程式碼靜態檢查規則檔
├── Dockerfile                 # 生產級容器打包建置檔
├── README.md                  # 專案完整架構與部署文檔
└── requirements.txt           # 專案 Python 相依清單

三、30 天完賽心路歷程:從 Prompt 到 System

如果說這 30 天帶給我最大的收穫是什麼,那就是體會到:「Prompt 只是引信,System 才是炸藥的本體。」

在 AI 浪潮初期,許多人以為做 AI 應用就是寫好一串神奇的咒語(Prompt)。但當你真正要把一個應用交到使用者手中時,你會發現:

LLM 不會幫你管理連線逾時

LLM 不會幫你防禦惡意爬蟲刷量

LLM 不能直接幫你查詢精準的 GPS 經緯度商圈

LLM 更不會在半夜程式報錯時發 Slack 或 Email 叫醒你修 Bug

所有的可靠性、使用者體驗與商業落地價值,全部依賴於傳統軟體工程中最扎實的環節:API 設計、微服務架構、狀態機控制、資料庫關聯、通訊加密、快取優化與自動化測試。

結語

感謝所有在這 30 天裡閱讀、按讚、留言與交流的夥伴們!
是你們的關注與反饋,讓這份原本孤獨的敲鍵盤過程充滿了動力。

這套系統的所有設計思路、架構實踐與原始程式碼,都將作為踏入 AI 工程化領域的一塊基石。
願我們都能在這場 AI 的時代洪流中,不只當一名 Prompt 的使用者,更成為能動手建造完整系統的優秀軟體架構師!


*提醒邦友,使用第三方服務/API 時,請務必評估資安風險與隱私保護
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言